/*
 ============================================================================
 文件名    : Line.cpp
 描述     : CLine类的实现.
 ============================================================================
 */

// 引用
#include "Line.h"
#include "Ball.h"
#include <e32math.h>

// ============================ 成员函数 ===============================

// ---------------------------------------------------------
// CLine::CLine
// 构造函数.
// ---------------------------------------------------------
//
CLine::CLine( TRealPoint aPoint1, TRealPoint aPoint2 ):iStart(aPoint1),iEnd(aPoint2)
	{
	}

// ---------------------------------------------------------
// CLine::Initialize
// 初始化线段的参数.
// ---------------------------------------------------------
//
void CLine::Initialize()
	{
	if( iStart.iX == iEnd.iX && iStart.iY == iEnd.iY )
		{
		return ;
		}
	if ( iStart.iX > iEnd.iX )
		{
		TRealPoint point = iStart;
		iStart = iEnd;
		iEnd = point;
		}
	if( iStart.iY == iEnd.iY )
		{
		iA = 0.0f;
		iB = 1.0f;
		}
	else if( iStart.iX == iEnd.iX )
		{
		iB = 0.0f;
		iA = 1.0f;
		}
	else
		{
		iB = 1.0f;
		iA = ( iStart.iY - iEnd.iY ) / ( iEnd.iX - iStart.iX );
		}
	iC = 0.0f - ( iA * iStart.iX + iB * iStart.iY );
	}

// ---------------------------------------------------------
// CLine::ConstructL
// 两段构造函数
// ---------------------------------------------------------
//
void CLine::ConstructL()
	{
	Initialize();
	}

// ---------------------------------------------------------
// CLine::NewL
// 构造函数
// ---------------------------------------------------------
//
CLine* CLine::NewL( TRealPoint aStart, TRealPoint aEnd )
	{
	CLine* self = new (ELeave)CLine( aStart, aEnd );
	CleanupStack::PushL( self );
	self->ConstructL();
	CleanupStack::Pop();
	return self;		
	}

// ---------------------------------------------------------
// CLine::GetStart
// 返回起始点
// ---------------------------------------------------------
//
TPoint CLine::GetStart()
	{
	return TPoint( (TInt)iStart.iX, (TInt)iStart.iY );
	}

// ---------------------------------------------------------
// CLine::SetStart
// 设置起始点
// ---------------------------------------------------------
//
void CLine::SetStart( TPoint aStart )
	{
	iStart.iX = aStart.iX;
	iStart.iY = aStart.iY;
	}

// ---------------------------------------------------------
// CLine::GetEnd
// 返回结束点
// ---------------------------------------------------------
//
TPoint CLine::GetEnd()
	{
	return TPoint( (TInt)iEnd.iX, (TInt)iEnd.iY );
	}

// ---------------------------------------------------------
// CLine::SetEnd
// 设置结束点并初始化参数
// ---------------------------------------------------------
//
void CLine::SetEnd( TPoint aEnd )
	{
	iEnd.iX = aEnd.iX;
	iEnd.iY = aEnd.iY;
	Initialize();
	}

// ---------------------------------------------------------
// CLine::GetDir
// 返回方向向量
// ---------------------------------------------------------
//
TRealVector CLine::GetDir()
	{
	return TRealVector( iEnd.iX - iStart.iX, iEnd.iY - iStart.iY );
	}

// ---------------------------------------------------------
// CLine::GetY
// 返回所在直线上某点的Y值
// ---------------------------------------------------------
//
TInt CLine::GetY( TInt aX )
	{
	if( IsVertical() )
		{
		return 0;
		}
	return TInt( 0.0f - iC - iA*aX );
	}

// ---------------------------------------------------------
// CLine::IsHorizonal
// 判断是否水平
// ---------------------------------------------------------
//
TBool CLine::IsHorizonal()
	{
	return iA == 0.0f;
	}

// ---------------------------------------------------------
// CLine::IsVertical
// 判断是否竖直
// ---------------------------------------------------------
//
TBool CLine::IsVertical()
	{
	return iB == 0.0f;
	}

// ---------------------------------------------------------
// CLine::Distance
// 返回某点到线段所在直线的距离
// ---------------------------------------------------------
//
TReal CLine::Distance( TPoint aPoint )
	{
	TReal dis = 0.0f;
	if( IsHorizonal() )
		{
		dis = aPoint.iY - GetY( aPoint.iX );
		}
	else if( IsVertical() )
		{
		dis = aPoint.iX - iStart.iX;
		}
	else 
		{
		TReal sqrtab;
		Math::Sqrt( sqrtab, iA*iA + iB*iB );
		dis = ( aPoint.iX * iA + aPoint.iY * iB + iC ) / sqrtab;
		}
	dis = ( dis >= 0.0f )? dis : ( 0.0f - dis );
	return dis;
	}

// ---------------------------------------------------------
// CLine::Hit
// 检测是否撞到小球
// ---------------------------------------------------------
//
TBool CLine::Hit( CBall* aBall )
	{
	TPoint center( TInt( aBall->GetPos().iX ), TInt( aBall->GetPos().iY ) );
	if( !IsVertical() && (center.iX <= iStart.iX || center.iX >= iEnd.iX ))
		{
		return EFalse;
		}
	TReal dist = Distance( center );
	return dist <= aBall->GetRad();
	}

// ---------------------------------------------------------
// CLine::Hit
// 返回某点到线段所在直线垂线的垂足
// ---------------------------------------------------------
//
TPoint CLine::GetPerFoot( TPoint aPoint )
	{
	if( IsHorizonal() )
		{
		return TPoint( aPoint.iX, TInt( iStart.iY ) );
		}
	if( IsVertical() )
		{
		return TPoint( TInt( iStart.iX ), aPoint.iY );
		}
	TReal kk = 0.0f - 1.0f / iA;
	TReal xx = ( kk - aPoint.iY - iA ) / ( iA + kk );
	TReal yy = kk*xx - kk*aPoint.iX + aPoint.iY;
	return TPoint( TInt( xx ), TInt( yy ) );
	}

// 文件结束
